﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CSCore;
using CSCore.Codecs.WAV;
using CSCore.MediaFoundation;
using CSCore.SoundIn;
using CSCore.Streams;
using FM.Common;
using FM.Events;
using FM.Services;
using FM.录音.Data;
using FM.录音.接口;
using FM.接口;
using Microsoft.Practices.Prism.Logging;
using Microsoft.Practices.Prism.PubSubEvents;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;
using NJT.IO;

namespace FM.录音.Services
{
    public class 录音服务wav : 启动基类, I录音服务
    {
        private WasapiCapture _输入声卡;
        private IWriteable _writer;
        private IWaveSource _finalSource;

        private IFm录音配置 _录音配置;


        public 录音服务wav(IUnityContainer 人事部cs, IEventAggregator 新闻部cs, IRegionManager 模块cs)
            : base(人事部cs, 新闻部cs, 模块cs)
        {
            新闻部.GetEvent<退出Event>().Subscribe(退出Action, true);
        }

        private void 退出Action(object obj)
        {
            停止录音();
        }

        public bool Is录音中 { get; set; }

        public void Set录音(bool 录音)
        {
            if (录音 && !Is录音中)
            {
                启动录音();
            }
            else if (!录音 && Is录音中)
            {
                停止录音();
            }
        }


        public IFm录音配置 录音配置
        {
            get { return _录音配置; }
            set { _录音配置 = value; }
        }


        private void 启动录音()
        {
            //return;

            if (录音配置 == null)
            {
                录音配置 = new Fm录音配置1();
            }

            var 声卡1 = 声卡设备.查找输入声卡(录音配置.录音声卡);
            if (声卡1 == null)
            {
                新闻部.GetEvent<状态栏更新Event>().Publish(new 状态栏Data1(Enum状态栏.提示, "没有输入声卡"));
                log.Log(ID + "没有输入声卡", Category.Exception, Priority.High);
                return;
            }
            Is录音中 = true;

            _输入声卡 = null;
            _输入声卡 = new WasapiCapture { Device = 声卡1 };
            _输入声卡.Initialize();

            var 目录名 = 目录.目录合并(录音配置.录音目录, DateTime.Now.ToString(运行状态.日期目录格式));
            if (!目录.目录检查并建立(目录名))
            {
                log.Log(ID + "无法创建目录:", Category.Warn, Priority.High);
                return;
            }

            var 文件名 = 目录.目录合并(目录名, DateTime.Now.ToString(运行状态.文件名格式)) + ".wav";

            log.Log(ID + "记录文件:" + 文件名, Category.Info, Priority.High);

            var soundInSource = new SoundInSource(_输入声卡);
            var singleBlockNotificationStream = new SingleBlockNotificationStream(soundInSource);
            _finalSource = singleBlockNotificationStream.ToWaveSource();

            //建立可共享的文件流
            Stream 文件流 = new FileStream(文件名, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
            _writer = new WaveWriter(文件流, _finalSource.WaveFormat);

            byte[] buffer = new byte[_输入声卡.WaveFormat.BytesPerSecond / 2];
            soundInSource.DataAvailable += (s, e) =>
            {
                int read;
                while ((read = _finalSource.Read(buffer, 0, buffer.Length)) > 0)
                    _writer.Write(buffer, 0, read);
            };

            _输入声卡.Start();
        }

        private void 停止录音()
        {
            if (Is录音中)
            {
                log.Log(ID + "停止记录文件", Category.Info, Priority.Low);
            }


            Is录音中 = false;

            if (_输入声卡 != null)
            {
                _输入声卡.Stop();
            }
            var writer2 = _writer as IDisposable;
            if (writer2 != null)
                writer2.Dispose();
        }

        public int ID { get; set; }
    }
}